package net.xdclass.config;

import cn.felord.payment.autoconfigure.EnableMobilePay;
import cn.felord.payment.wechat.v3.WechatApiProvider;
import cn.felord.payment.wechat.v3.WechatDirectPayApi;
import cn.felord.payment.wechat.v3.WechatPayCallback;
import com.sun.nio.sctp.NotificationHandler;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.notification.NotificationRequest;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.Data;
import net.xdclass.annotation.RepeatSubmit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.stream.Collectors;

/**
 * 小滴课堂,愿景：让技术不再难学
 *
 * @Description
 * @Author 二当家小D
 * @Remark 有问题直接联系我，源码-笔记-技术交流群
 * @Version 1.0
 **/

@Data
@Configuration
@ConfigurationProperties(prefix = "wechat.pay.v3.native")
@EnableMobilePay
public class WechatPayConfig {


	public static final String TENANT_ID = "native";





    /*        #  应用appId  服务商模式下为服务商的appid 必填
    app-id: wx886cfd75c076d64e
        #  api v3 密钥 必填
    app-v3-secret: UtFDN84CXYv7pq0QkroHz1e4FGtEx32e
        #  微信支付商户号 服务商模式下为服务商的mchid 必填
    mch-id: 1635570942
        #  商户服务器域名 用于回调  需要放开回调接口的安全策略 必填
    domain: https://baidu.com
        #  商户 api 证书路径 必填  填写classpath路径 位于 maven项目的resources文件下
    cert-path: /cert/apiclient_cert.p12*/

	private String appId;
	private String appV3Secret;
	private String mchId;
	private String domain;
	private String notifyUrl;
	private String certPath;
	private String privateKeyPath;

	private String mchSerialNo;

	@Autowired
	private WechatApiProvider wechatApiProvider;


	@Bean("wechatPayService")
	public WechatDirectPayApi getWechatPayApi() {
		return wechatApiProvider.directPayApi(TENANT_ID);
	}


	@Bean("wechatPayCallback")
	public WechatPayCallback getWechatPayCallback() {
		return wechatApiProvider.callback(TENANT_ID);
	}


	@Bean("certificatesVerifier")
	public Verifier getCertificatesVerifier() throws IOException, NotFoundException, GeneralSecurityException, HttpCodeException {

		// 使用定时更新的签名验证器，不需要传入证书
//        ScheduledUpdateCertificatesVerifier verifier = null;
//        verifier = new ScheduledUpdateCertificatesVerifier(
//            new WechatPay2Credentials(payConfig.getMchId(),
//                new PrivateKeySigner(payConfig.getMchSerialNo(),
//                    getPrivateKey())),
//            payConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
		PrivateKey merchantPrivateKey = getPrivateKey();
		// 获取证书管理器实例
		CertificatesManager certificatesManager = CertificatesManager.getInstance();
		// 向证书管理器增加需要自动更新平台证书的商户信息
		certificatesManager.putMerchant(mchId, new WechatPay2Credentials(mchId,
				new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),
			appV3Secret.getBytes(StandardCharsets.UTF_8));
		// 从证书管理器中获取verifier
		Verifier verifier = certificatesManager.getVerifier(mchId);

		return verifier;
	}


	public static class Url {

		/**
		 * native下单接口
		 */
		public static final String NATIVE_ORDER = "https://api.mch.weixin.qq.com/v3/pay/transactions/native";
		public static final String NATIVE_ORDER_PATH = "/v3/pay/transactions/native";


		/**
		 * native订单查询接口，根据商户订单号查询
		 * 一个是根据微信订单号，一个是根据商户订单号
		 */
		public static final String NATIVE_QUERY = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s?mchid=%s";
		public static final String NATIVE_QUERY_PATH = "/v3/pay/transactions/out-trade-no/%s?mchid=%s";


		/**
		 * native关闭订单接口
		 */
		public static final String NATIVE_CLOSE = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/%s/close";
		public static final String NATIVE_CLOSE_PATH = "/v3/pay/transactions/out-trade-no/%s/close";

	}


	public PrivateKey getPrivateKey() throws IOException {
		InputStream inputStream = new ClassPathResource(privateKeyPath.replace("classpath:", "")).getInputStream();

		String content = new BufferedReader(new InputStreamReader(inputStream))
			.lines().collect(Collectors.joining(System.lineSeparator()));

		try {
			String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
				.replace("-----END PRIVATE KEY-----", "")
				.replaceAll("\\s+", "");
			KeyFactory kf = KeyFactory.getInstance("RSA");

			PrivateKey finalPrivateKey = kf.generatePrivate(
				new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));

			return finalPrivateKey;

		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException("当前Java环境不支持RSA", e);
		} catch (InvalidKeySpecException e) {
			throw new RuntimeException("无效的密钥格式");
		}
	}


}
